/**
 * @file rgb2.c
 * @author your name (you@domain.com)
 * @brief 生成一个彩色条的BMP
 * @version 0.1
 * @date 2021-04-28
 * 
 * @copyright Copyright (c) 2021
 * 
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>


/*
424d 368c0a00 00 00 00003600 0000  BM6.......6...
28 00000080 02000068 0100 0001 00  (.......h.....
180000 00000000 00000000 000000  ..............
00 00000000 00000000000000ffff  ..............
ff11111111111111111111111111  ..............
1111111111111111111111111111  ..............
1111111111111111111111111111

424d:  bfType  2字节 	标识，就是“BM” 	BM
368c0a00: bfSize 4字节 	整个 BMP 文件的大小
00 :bfReserved1 	2字节 	保留字
00 :bfReserved2 	2字节 	保留字 
00003600: 	bfOffBits 	4字节 	偏移数，即位图文件头+位图信息头+调色板的大小


000028：biSize 	4字节 	位图信息头的大小，为40
00000080    ：biWidth 	4字节 	位图的宽度，单位是像素 	
02000068    ：biHeight 	4字节 	位图的高度，单位是像素
0100：biPlanes 	2字节 	固定值1 	1
0001：biBitCount 	2字节 	每个像素的位数 1-黑白图，4-16色，8-256色，24-真彩色，32-带 alpha 通道
00180000：biCompression 	4字节 	压缩方式，BI_RGB(0)为不压缩
00000000：biSizeImage 	4字节 	位图全部像素占用的字节数，BI_RGB时可设为0
00000000：biXPelsPerMeter 	4字节 	水平分辨率(像素/米) 	
00000000：biYPelsPerMeter 	4字节 	垂直分辨率(像素/米)
00000000：biClrUsed 	4字节 	位图使用的颜色数 如果为0，则颜色数为2的biBitCount次方 	
00000000：biClrImportant 	4字节 	重要的颜色数，0代表所有颜色都重要 	
*/

uint32_t rainbowColors[] = {
    0XFF0000, // 红
    0XFFA500, // 橙
    0XFFFF00, // 黄
    0X00FF00, // 绿
    0X007FFF, // 青
    0X0000FF, // 蓝
    0X8B00FF  // 紫
};

typedef struct
{
    uint8_t bfSize;//整个 BMP 文件的大小
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    unsigned int bfOffBits;//偏移数，即位图文件头+位图信息头+调试板大小
} BitmapFileHeader;

typedef struct
{
    uint32_t biSize;
    int biWidth;
    int biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int biXPelsPerMeter;
    int biYPelsPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImportant;
} BitmapInfoHeader;

void writeRGBToBmp(char *filename, int width, int height);

int main(void)
{
    writeRGBToBmp("rainbow_700x700.bmp", 700, 700);
    return 0;
}
void writeRGBToBmp(char *filename, int width, int height)
{
    FILE *bitmapFile = fopen(filename, "wb");
    if (!bitmapFile)
    {
        printf("fopen[%s]\n", strerror(errno));
        return;
    }
    uint16_t bfType = 0x4d42; //固定头部,转换为字符为 'B' 'M'

    BitmapFileHeader fileHeader;
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfSize = 2 + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + width * height * 3;
    fileHeader.bfOffBits = 0x36;//固定 0x36

    BitmapInfoHeader infoHeader;
    infoHeader.biSize = sizeof(BitmapInfoHeader);//文件信息头
    infoHeader.biWidth = width;//位图的宽度
    
    //biHeight 为正，位图自底向顶扫描，biHeight 为负，位图自顶向底扫描。
    infoHeader.biHeight = -height;//位图的高度
    infoHeader.biPlanes = 1;//固定值1
    infoHeader.biBitCount = 24; //每个像素的位数 ，可以是1-黑白 4-16色 8-256色 24-真彩色 32 带透明
    infoHeader.biCompression = 0;//压缩方式，BI_RGB(0)为不压缩
    infoHeader.biSizeImage = 0;//当biCompression为BI_RGB时，可设置为0
    
    /* 不清楚这里的 biXPelsPerMeter(水平分辨率)和biYPelsPerMeter(垂直分辨率)的作用和影响 */
    infoHeader.biXPelsPerMeter = 5000;
    infoHeader.biYPelsPerMeter = 5000;
    infoHeader.biClrUsed = 0;
    infoHeader.biClrImportant = 0;

    fwrite(&bfType, sizeof(bfType), 1, bitmapFile);
    fwrite(&fileHeader, sizeof(fileHeader), 1, bitmapFile);
    fwrite(&infoHeader, sizeof(infoHeader), 1, bitmapFile);

    int j = 1;
    for (int i = 0; i < width; i++)
    {
        uint32_t currentColor = rainbowColors[0];

        if (i < j * 100)
        {
            currentColor = rainbowColors[j - 1];
        }
        else
        {
            j++;
            //// 一旦进入else 则 currentColor 不会发生变化，需要取消这次循环对 i 的变化。 
            i--;
            continue;
        }

        uint8_t R = (currentColor & 0xFF0000) >> 16;
        uint8_t G = (currentColor & 0x00FF00) >> 8;
        uint8_t B = (currentColor & 0x0000FF) >> 0;

        for (int i = 0; i < height; i++)
        {
            //将 BGR 顺序写入一个像素 RGB 24 到文件中 //如果按照 RGB 来放置，则显示的不是理想效果
            fwrite(&B, 1, 1, bitmapFile);
            fwrite(&G, 1, 1, bitmapFile);
            fwrite(&R, 1, 1, bitmapFile);
        }
        
    }

    fclose(bitmapFile);
}

